package au.org.htd.youslide.servlets;

import java.io.IOException;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.json.JSONArray;
import org.json.JSONException;

import au.org.htd.youslide.AppException;
import au.org.htd.youslide.PMF;
import au.org.htd.youslide.SongProject;
import au.org.htd.youslide.Tag;
import au.org.htd.youslide.Util;
import au.org.htd.youslide.ppt.DisplayText;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

@SuppressWarnings("serial")
public class SlidesServlet extends HttpServlet {
   private static final Logger log = Logger.getLogger(SlidesServlet.class
         .getName());

   public void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {

      String requestType = req.getParameter("requestType");
      if ("create".equals(requestType)) {
         doCreate(req, resp);
      } else if ("save".equals(requestType)) {
         doSave(req, resp);
      } else {
         log.info("NO REQUEST TYPE!!!");
      }
   }

   public void doGet(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      String requestType = req.getParameter("requestType");
      if ("delete".equals(requestType)) {
         doDeleteSong(req, resp);
      } else if ("edit".equals(requestType)) {
         doEdit(req, resp);
      } else if ("attachAudio".equals(requestType)) {
         doAttachAudio(req, resp);
      } else if ("removeAudio".equals(requestType)) {
         doRemoveAudio(req, resp);
      } else if ("attachObj".equals(requestType)) {
         doAttachObj(req, resp);
      } else if ("getTags".equals(requestType)) {
         doGetTags(req, resp);
      } else if ("addTag".equals(requestType)) {
         doAddTag(req, resp);
      } else if ("removeTag".equals(requestType)) {
         doRemoveTag(req, resp);
      } else {
         log.info("NO REQUEST TYPE!!!");
      }
   }

   private void doCreate(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      HttpSession session = req.getSession();
      session.removeAttribute("id");
      String englishName = req.getParameter("englishName");
      if ("English name".equals(englishName)) {
         englishName = "";
      }
      String chineseName = req.getParameter("chineseName");
      if ("Chinese name".equals(chineseName)) {
         chineseName = "";
      }
      session.setAttribute("englishName", englishName);
      session.setAttribute("chineseName", chineseName);

      resp.sendRedirect("/create.jsp");
   }

   private void doEdit(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      Long id = Long.parseLong(req.getParameter("id"));
      SongProject song = new SongProject(PMF.getPM()).get(id);

      HttpSession session = req.getSession();
      session.setAttribute("id", id);
      session.setAttribute("bgId", song.getBackgroundId());
      session.setAttribute("englishLyrics", song.getEnglishLyrics());
      session.setAttribute("chineseLyrics", song.getChineseLyrics());
      session.setAttribute("englishName", song.getEnglishName());
      session.setAttribute("chineseName", song.getChineseName());

      resp.sendRedirect("/create.jsp");
      song.closeConnection();
   }

   private void doAttachAudio(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      Long id = Long.parseLong(req.getParameter("id"));
      String audioUrl = req.getParameter("url");
      SongProject song = new SongProject(PMF.getPM()).get(id);
      song.setAudioUrl(audioUrl);
      song.save();
      resp.getWriter().write(song.getAudioUrl());
      song.closeConnection();
   }

   private void doAttachObj(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      Long id = Long.parseLong(req.getParameter("id"));
      String url = req.getParameter("url");
      PersistenceManager pm = PMF.getPM();
      SongProject song = new SongProject(pm).get(id);
      try {
         song.attach(url);
      } catch (AppException e) {
         log.info(e.getMessage());
         resp.getWriter().write(e.getMessage());
         pm.close();
         return;
      }
      song.save();
      resp.getWriter().write("" + (song.getAttachments().size() - 1));
      song.closeConnection();
   }

   private void doRemoveAudio(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      Long id = Long.parseLong(req.getParameter("id"));
      SongProject song = new SongProject(PMF.getPM()).get(id);
      song.setAudioUrl(null);
      song.save();
      song.closeConnection();
   }

   private void doSave(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      String englishName = req.getParameter("englishName");
      String chineseName = req.getParameter("chineseName");
      if (Util.isEmpty(englishName) && Util.isEmpty(chineseName)) {
         englishName = "Song";
         chineseName = "歌";
      }
      String englishLyrics = req.getParameter("englishLyrics")
            .replace("\n", "");
      if ("English lyrics".equals(englishLyrics)) {
         englishLyrics = "";
      }
      String chineseLyrics = req.getParameter("chineseLyrics")
            .replace("\n", "");
      if ("Chinese lyrics".equals(chineseLyrics)) {
         chineseLyrics = "";
      }
      String backgroundId = req.getParameter("backgroundId");
      String id = req.getParameter("id");

      SongProject song = null;
      song = new SongProject(PMF.getPM());
      if (!Util.isEmpty(id)) {
         song = song.get(Long.parseLong(id));
         String audioUrl = song.getAudioUrl();
         // if editor is different to creator
         UserService userService = UserServiceFactory.getUserService();
         if (!song.getCreatorName().equals("anonymous")
               && song.getCreator().compareTo(userService.getCurrentUser()) != 0) {
            song = new SongProject(PMF.getPM());
            song.setAudioUrl(audioUrl);
         }
      } else {
         song = song.save();
      }
      User user = UserServiceFactory.getUserService().getCurrentUser();
      song.setCreator(user);
      song.setLastUpdate(new Date());
      song.setLyrics(new DisplayText(englishLyrics, chineseLyrics));
      song.setName(new DisplayText(englishName, chineseName));
      if (null != backgroundId) {
         song.setBackgroundId(new Long(backgroundId));
      }

      String tags = req.getParameter("tags");
      if (null != tags) {
         StringTokenizer tok = new StringTokenizer(tags, ",");
         while (tok.hasMoreTokens()) {
            Util.tag(tok.nextToken(), song);
         }
      }

      song = song.save();
      song.closeConnection();

      HttpSession session = req.getSession();
      session.setAttribute("id", song.getId());
      session.setAttribute("letter", song.getFirstLetter().toUpperCase());
      resp.sendRedirect("/library.jsp");
   }

   private void doDeleteSong(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      Long id = Long.parseLong(req.getParameter("id"));
      SongProject song = new SongProject(PMF.getPM()).get(id);
      song.delete();
      song.closeConnection();

      String letter = req.getParameter("letter");
      resp.getWriter().write("" + SongProject.searchByLetter(letter).length());
   }

   private void doGetTags(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      Long songId = Long.parseLong(req.getParameter("songId"));
      SongProject song = new SongProject(PMF.getPM()).get(songId);
      try {
         JSONArray tags;
         tags = song.getTagsArray();
         resp.setCharacterEncoding("UTF-8");
         resp.getWriter().write(tags.toString());
      } catch (JSONException e) {
         log.info(e.getMessage());
      } finally {
         song.closeConnection();
      }
   }

   private void doAddTag(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      String tagName = req.getParameter("tag");
      Long songId = Long.parseLong(req.getParameter("songId"));
      Util.tag(tagName, songId);
   }

   private void doRemoveTag(HttpServletRequest req, HttpServletResponse resp)
         throws IOException {
      String tagName = req.getParameter("tag");
      Long songId = Long.parseLong(req.getParameter("songId"));
      SongProject song = new SongProject(PMF.getPM()).get(songId);
      song.removeTag(tagName);
      Tag tag = Tag.getTagByName(song.getPm(), tagName);
      if (null != tag) {
         tag.removeSong(songId);
      }
      song.closeConnection();
   }
}
